package cn.iocoder.boot;

import cn.iocoder.boot.domin.Car;
import com.alibaba.fastjson.JSON;
import org.hyperledger.fabric.contract.Context;
import org.hyperledger.fabric.contract.ContractInterface;
import org.hyperledger.fabric.contract.annotation.*;
import org.hyperledger.fabric.shim.ChaincodeException;
import org.hyperledger.fabric.shim.ledger.KeyValue;
import org.hyperledger.fabric.shim.ledger.QueryResultsIterator;

import java.util.ArrayList;
import java.util.List;

@Contract(
        name = "CarTransfer",
        info = @Info(
                title = "CarTransfer",
                description = "车辆流转",
                version = "0.0.1",
                license = @License(
                        name = "Apache 2.0 License",
                        url = "https://www.apache.org/licenses/LICENSE-2.0.html"
                ),
                contact = @Contact(
                        email = "252048765@qq.com",
                        name = "lrl",
                        url = "https://hyperledger.example.com"
                )
        )
)
@Default
public class CarTransfer implements ContractInterface {

    /**
     * 初始化车辆信息
     *
     * @param ctx 上下文
     */
    @Transaction(intent = Transaction.TYPE.SUBMIT)
    public void InitLedger(final Context ctx) {
        putCar(ctx, new Car().setBrand("奔驰").setFrameNumber("A123456789").setPlateNumber("京A12345").setColor("黑色").setOwner("张三"));
        putCar(ctx, new Car().setBrand("宝马").setFrameNumber("B123456789").setPlateNumber("京B12345").setColor("蓝色").setOwner("李四"));
        putCar(ctx, new Car().setBrand("奥迪").setFrameNumber("C123456789").setPlateNumber("京C12345").setColor("白色").setOwner("王五"));
        putCar(ctx, new Car().setBrand("小米su7").setFrameNumber("D123456789").setPlateNumber("京D12345").setColor("黑色").setOwner("赵六"));
    }

    /**
     * 创建车辆信息
     * @param ctx 上下文
     * @param frameNumber 车架号
     * @param plateNumber 车牌号
     * @param color 颜色
     * @param owner 所有者
     * @return 车辆信息
     */
    @Transaction(intent = Transaction.TYPE.SUBMIT)
    public Car CreateCar(final Context ctx, final String frameNumber, final String plateNumber, final String color, final String owner) {
        if (CarExists(ctx, frameNumber)){
            throw new ChaincodeException("车辆已存在", "0001");
        }
        Car car = new Car().setFrameNumber(frameNumber).setPlateNumber(plateNumber).setColor(color).setOwner(owner);
        return putCar(ctx, car);
    }

    /**
     * 更新车辆信息
     * @param ctx 上下文
     * @param car 车辆信息
     * @return 车辆信息
     */
    @Transaction(intent = Transaction.TYPE.SUBMIT)
    public Car UpdateCar(final Context ctx, final Car car) {
        String jsonString = JSON.toJSONString(car);
        ctx.getStub().putStringState(car.getFrameNumber(), jsonString);
        return car;
    }

    /**
     * 删除车辆信息
     * @param ctx 上下文
     * @param frameNumber 车架号
     */
    @Transaction(intent = Transaction.TYPE.SUBMIT)
    public void DeleteCar(final Context ctx, final String frameNumber) {
        Car car = GetCar(ctx, frameNumber);
        if (car == null){
            throw new ChaincodeException("车辆不存在", "0002");
        }
        ctx.getStub().delState(frameNumber);
    }

    /**
     * 获取车辆信息
     * @param ctx 上下文
     * @param frameNumber 车架号
     * @return 车辆信息
     */
    @Transaction(intent = Transaction.TYPE.EVALUATE)
    public Car GetCar(final Context ctx, final String frameNumber) {
        String stringState = ctx.getStub().getStringState(frameNumber);
        if (stringState == null || stringState.isEmpty()){
            throw new ChaincodeException("车辆不存在", "0002");
        }
        return JSON.parseObject(stringState, Car.class);
    }

    /**
     * 判断车辆是否存在
     * @param ctx 上下文
     * @param frameNumber 车架号
     * @return true/false
     */
    @Transaction(intent = Transaction.TYPE.EVALUATE)
    public Boolean CarExists(final Context ctx, final String frameNumber) {
        String carAsBytes = ctx.getStub().getStringState(frameNumber);
        return carAsBytes != null && !carAsBytes.isEmpty();
    }


    /**
     * 获取所有车辆信息
     * @param ctx 上下文
     * @return 所有车辆信息
     */
    @Transaction(intent = Transaction.TYPE.EVALUATE)
    public String GetAllCars(final Context ctx) {
        QueryResultsIterator<KeyValue> stateByRange = ctx.getStub().getStateByRange("", "");
        List<Car> cars = new ArrayList<>();
        for (KeyValue keyValue : stateByRange) {
            Car car = JSON.parseObject(keyValue.getValue(), Car.class);
            cars.add(car);
        }
        return JSON.toJSONString(cars);
    }


    private Car putCar(final Context ctx, final Car car) {
        String sortedJson = JSON.toJSONString(car);
        ctx.getStub().putStringState(car.getFrameNumber(), sortedJson);
        return car;
    }

}
